SSH 连接建立与认证
本文主要描述 SSH 链接建立与认证的一般过程。
前提: 服务器有自己的公钥和私钥,客户端有自己的公钥和私钥,并且服务器要被连接的用户的 ~/.ssh/authorized_keys 中记录了客户端的公钥。
SSH 连接建立要经历以下过程 (SSH 协议的不同实现在细节上有不同,以 OpenSSH 为例):
- 连接建立: 客户端向远程服务器发起 SSH 连接请求并建立连接
- 协商通信方式: 客户端与服务器协商协议版本、密钥交换算法、身份认证方法、压缩算法等等内容
- 使用密钥交换算法 (DH/ECDH) 协商对称加密密钥:
- 客户端与服务器使用协商出的密钥交换算法 (DH/ECDH 算法) 协商出对称加密密钥。此后该会话所有的通信都用该密钥加密
- 客户端确认服务器身份: 服务器把自己的公钥发给客户端,客户端确认公钥指纹
- 如果本次服务器发来的公钥指纹在本地没有记录,那就记录服务器的公钥指纹,继续下一步
- 如果本次服务器发来的公钥指纹与上次记录的指纹匹配,继续下一步
- 如果本次服务器发来的公钥指纹与上次记录的指纹不匹配,那么可能存在中间人攻击,连接中断
- 服务器确认客户端身份:
- 对于使用密码认证的方式来说
- 客户端用服务器的公钥把密码加密后发给服务器
- 服务器用自己的私钥解密出密码
- 服务器把解密出的密码与本地对应用户的密码比对,若相同,身份验证通过
- 对于使用非对称加密验证身份的方式来说
- 客户端收集当前连接的信息组成待签名数据:
- 会话 ID (Session ID): 是 SSH 会话的唯一标识符,用于标识当前会话的开始,通常在 SSH 握手过程中生成,并在整个会话期间保持不变
- 消息类型 (Message Type): 是身份验证请求的消息类型,通常是 SSH2_MSG_USERAUTH_REQUEST。这指示了消息的目的,即执行用户身份验证
- 用户名 (User Name): 要进行身份验证的用户名,标识要连接的用户
- 服务名称 (Service Name): 正在请求身份验证的服务的名称。通常,值为 "ssh-connection"
- 身份验证方法 (Authentication Method): 要使用的身份验证方法,例如 "publickey" (公钥身份验证) 或 "password" (密码身份验证)
- 签名算法 (Signature Algorithm): 是用于签名待签名数据的签名算法,它指定了如何对数据进行加密和验证
- 身份密钥 (Identity Key): 用于身份验证的客户端身份密钥的相关信息,通常包括密钥类型、公钥和相关元数据
- 主机密钥 (Host Key): 如果正在进行主机绑定,还会包括主机密钥的相关信息,用于确保与服务器的通信安全性
- 客户端计算待签名信息的 hash 值并用客户端的私钥加密
- 客户端把待签名数据和被私钥加密的 hash 值发给服务器
- 服务器利用客户端发来的待签名数据再次计算 hash 值
- 服务器用客户端的公钥解密出客户端发来的、从客户端生成的、被加密后的 hash 值
- 服务器比较两个 hash 值,若相同,身份验证通过
- 客户端收集当前连接的信息组成待签名数据:
- 对于使用密码认证的方式来说
- 建立会话: 客户端向服务器端发送会话请求,请求服务器提供某种类型的服务 (Stelnet, SFTP, SCP, NETCONF)
SSH 登录过程中用户需要关注、配置的只有两个阶段:
- 使用密钥交换算法 (DH/ECDH) 协商对称加密密钥
ssh -Q kex
可以查看当前版本的 OpenSSH 支持什么密钥交换算法
- 服务器确认客户端身份
- 用密码认证还是非对称加密认证
ssh -Q key
可以查看当前版本的 OpenSSH 在使用非对称加密的身份认证过程中,支持什么样的密钥类型